package com.glSto.controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.bind.annotation.*;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.crypto.Cipher;

/**
 * 组织数据同步API控制器
 * 提供可被外部调用的RESTful接口
 */
@RestController
@RequestMapping("/api/access-control")
public class AccessControlSystem_ZZ {
    // 日志记录器
    private static final Logger mainDataLogger = LoggerFactory.getLogger("com.glSto.controller.AccessControlSystem.mainData");
    private static final Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd HH:mm:ss")  // 支持空格分隔的日期格式
            .create();

    // 从配置文件读取参数（静态字段支持静态内部类访问）
    @Value("${token.api.url:https://10.105.0.5:443/evo-apigw/evo-oauth/1.0.0/oauth/extend/token}")
    private String tokenApiUrl;

    @Value("${organization.api.base.url:https://10.105.0.5:443/evo-apigw/evo-brm/1.2.0/organization/page}")
    private String organizationApiBaseUrl;

    @Value("${public.key.api:https://10.105.0.5:443/evo-apigw/evo-oauth/1.0.0/oauth/public-key}")
    private String publicKeyApi;

    // 静态字段 - 支持静态内部类访问
    private static String fixedClientId;
    private static String fixedClientSecret;
    private static String fixedGrantType;

    @Value("${db.url:jdbc:oracle:thin:@//10.105.45.14:1521/GLPC_CDB01_PDB06}")
    private String dbUrl;

    @Value("${db.username:ats}")
    private String dbUsername;

    @Value("${db.password:Power4005}")
    private String dbPassword;

    // 静态字段的setter方法（用于Spring注入）
    @Value("${client.id:wuyanggao}")
    public void setFixedClientId(String clientId) {
        fixedClientId = clientId;
    }

    @Value("${client.secret:42bec152-8f04-476a-9aec-e7d616ff3cb3}")
    public void setFixedClientSecret(String clientSecret) {
        fixedClientSecret = clientSecret;
    }

    @Value("${grant.type:password}")
    public void setFixedGrantType(String grantType) {
        fixedGrantType = grantType;
    }

    // 分页参数常量
    private static final int DEFAULT_PAGE_SIZE = 100;
    private static final int DEFAULT_PAGE_NUM = 1;
    // OAuth 2.0 Bearer Token前缀
    private static final String OAUTH_BEARER_PREFIX = "Bearer ";

    // HTTPS证书处理（跳过证书校验）
    static {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() { return null; }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
                    }
            };
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HostnameVerifier allHostsValid = (hostname, session) -> true;
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (Exception e) {
            mainDataLogger.error("SSL初始化异常", e);
            throw new RuntimeException("SSL初始化失败，影响HTTPS请求", e);
        }
    }

    /**
     * 同步组织数据API接口
     * 外部系统可通过POST请求调用此接口触发数据同步
     *
     * @param request 请求对象，包含认证信息
     * @param authInfo 包含用户名和密码的认证信息
     * @return 同步结果
     */
    @PostMapping("/AccessControlSystem_ZZ")
    public Map<String, Object> syncOrganizations(HttpServletRequest request,
                                                 @RequestBody AuthInfo authInfo) {
        Map<String, Object> result = new HashMap<>();
        long startTime = System.currentTimeMillis();

        try {
            mainDataLogger.info("开始组织数据同步，请求IP: {}", getClientIp(request));

            // 1. 获取OAuth 2.0 Access Token
            TokenData tokenData = getOAuthAccessToken(authInfo.getUsername(), authInfo.getPassword());
            String accessToken = tokenData.getAccess_token();

            // 2. 循环查询所有组织数据并同步到数据库
            List<OrganizationItem> allOrganizations = queryAllOrganizations(accessToken);

            // 3. 构建成功响应
            result.put("success", true);
            result.put("message", "组织数据同步成功");
            result.put("totalCount", allOrganizations.size());
            result.put("duration", System.currentTimeMillis() - startTime);
            mainDataLogger.info("组织数据同步完成，共同步 {} 条记录，耗时 {}ms",
                    allOrganizations.size(), System.currentTimeMillis() - startTime);

        } catch (Exception e) {
            mainDataLogger.error("组织数据同步失败", e);
            result.put("success", false);
            result.put("message", "组织数据同步失败: " + e.getMessage());
            result.put("duration", System.currentTimeMillis() - startTime);
        }

        return result;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    // 带OAuth鉴权的POST请求方法
    private String sendHttpsPostWithOAuth(String apiUrl, Object requestParam, String accessToken) {
        if (accessToken == null || accessToken.trim().isEmpty()) {
            String errMsg = "OAuth 2.0鉴权失败：access_token为空";
            mainDataLogger.error(errMsg);
            throw new IllegalArgumentException(errMsg);
        }

        StringBuilder response = new StringBuilder();
        HttpsURLConnection connection = null;
        OutputStream outputStream = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            URL url = new URL(apiUrl);
            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(8000);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            connection.setRequestProperty("Authorization", OAUTH_BEARER_PREFIX + accessToken);
            mainDataLogger.info("接口[{}]鉴权头：{}", apiUrl, OAUTH_BEARER_PREFIX + accessToken);

            // 序列化请求体并打印日志
            String rawJsonRequest = gson.toJson(requestParam);
            mainDataLogger.info("接口[{}]请求体：\n{}", apiUrl, rawJsonRequest);

            outputStream = connection.getOutputStream();
            outputStream.write(rawJsonRequest.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();

            int responseCode = connection.getResponseCode();
            inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream();
            if (responseCode >= 300) {
                String errMsg = String.format("接口[%s]请求失败，响应码：%d", apiUrl, responseCode);
                mainDataLogger.error(errMsg);
                response.append(errMsg).append("\n");
                if (responseCode == 401) response.append("提示：可能是access_token无效、过期或格式错误\n");
                else if (responseCode == 403) response.append("提示：当前Token无此接口访问权限\n");
            }

            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) response.append(line);
            mainDataLogger.info("接口[{}]响应内容：\n{}", apiUrl, response.toString());

        } catch (IOException e) {
            mainDataLogger.error("接口[{}]POST请求异常", apiUrl, e);
            response.append("请求异常：").append(e.getMessage());
        } finally {
            closeResources(reader, inputStream, connection);
            try { if (outputStream != null) outputStream.close(); }
            catch (IOException e) { mainDataLogger.error("POST输出流关闭异常", e); }
        }
        return response.toString();
    }

    // 带OAuth鉴权的GET请求方法（支持URL参数拼接）
    private String sendHttpsGetWithOAuth(String apiBaseUrl, String accessToken, String... params) {
        if (accessToken == null || accessToken.trim().isEmpty()) {
            String errMsg = "OAuth 2.0鉴权失败：access_token为空";
            mainDataLogger.error(errMsg);
            throw new IllegalArgumentException(errMsg);
        }

        // 拼接URL参数
        StringBuilder urlBuilder = new StringBuilder(apiBaseUrl);
        if (params != null && params.length > 0) {
            urlBuilder.append("?");
            for (int i = 0; i < params.length; i++) {
                urlBuilder.append(params[i]);
                if (i < params.length - 1) {
                    urlBuilder.append("&");
                }
            }
        }
        String finalApiUrl = urlBuilder.toString();

        StringBuilder response = new StringBuilder();
        HttpsURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            URL url = new URL(finalApiUrl);
            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(8000);
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            connection.setRequestProperty("Authorization", OAUTH_BEARER_PREFIX + accessToken);
            mainDataLogger.info("接口[{}]鉴权头：{}", finalApiUrl, OAUTH_BEARER_PREFIX + accessToken);

            int responseCode = connection.getResponseCode();
            inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream();
            if (responseCode >= 300) {
                String errMsg = String.format("接口[%s]请求失败，响应码：%d", finalApiUrl, responseCode);
                mainDataLogger.error(errMsg);
                response.append(errMsg).append("\n");
                if (responseCode == 401) response.append("提示：可能是access_token无效、过期或格式错误\n");
                else if (responseCode == 403) response.append("提示：当前Token无此接口访问权限\n");
            }

            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) response.append(line);
            mainDataLogger.info("接口[{}]响应内容：\n{}", finalApiUrl, response.toString());

        } catch (IOException e) {
            mainDataLogger.error("接口[{}]GET请求异常", finalApiUrl, e);
            response.append("请求异常：").append(e.getMessage());
        } finally {
            closeResources(reader, inputStream, connection);
        }
        return response.toString();
    }

    // GET请求方法（获取公钥用）
    private String sendHttpsGetRequest(String apiUrl) {
        StringBuilder response = new StringBuilder();
        HttpsURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            URL url = new URL(apiUrl);
            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

            int responseCode = connection.getResponseCode();
            inputStream = (responseCode == HttpsURLConnection.HTTP_OK) ? connection.getInputStream() : connection.getErrorStream();
            if (responseCode != HttpsURLConnection.HTTP_OK) {
                String errMsg = "GET请求失败，响应码：" + responseCode;
                mainDataLogger.error(errMsg);
                response.append(errMsg).append("\n");
            }

            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) response.append(line);
        } catch (IOException e) {
            mainDataLogger.error("GET请求异常", e);
            response.append("GET请求异常：").append(e.getMessage());
        } finally {
            closeResources(reader, inputStream, connection);
        }
        return response.toString();
    }

    // 获取OAuth 2.0 Access Token
    private TokenData getOAuthAccessToken(String username, String plainPassword) throws Exception {
        // 1. 获取公钥
        String publicKeyResponse = sendHttpsGetRequest(publicKeyApi);
        String publicKey = extractPublicKey(publicKeyResponse);
        if (publicKey == null) {
            throw new RuntimeException("获取公钥失败，无法加密密码");
        }

        // 2. 加密密码
        String encryptedPassword = encrypt(plainPassword, publicKey);
        mainDataLogger.info("密码加密完成，加密后长度：{}", encryptedPassword.length());

        // 3. 构造Token请求参数
        TokenRequest tokenRequest = new TokenRequest(username, encryptedPassword, publicKey);
        String tokenRequestJson = gson.toJson(tokenRequest);
        mainDataLogger.info("Token接口（获取access_token）请求体：\n{}", tokenRequestJson);

        // 4. 调用Token接口
        String tokenResponseJson = sendHttpsPostWithOAuth(tokenApiUrl, tokenRequest, "NO_AUTH_NEEDED");
        TokenResponse tokenResponse = gson.fromJson(tokenResponseJson, TokenResponse.class);

        // 5. 校验Token响应
        if (tokenResponse == null || !tokenResponse.isSuccess() || tokenResponse.getData() == null) {
            String errMsg = String.format("获取access_token失败，错误码：%s，错误信息：%s",
                    tokenResponse.getCode(), tokenResponse.getErrMsg());
            mainDataLogger.error(errMsg);
            throw new RuntimeException(errMsg);
        }

        TokenData tokenData = tokenResponse.getData();
        mainDataLogger.info("获取access_token成功，有效期：{}秒，Token类型：{}",
                tokenData.getExpires_in(), tokenData.getToken_type());
        return tokenData;
    }

    // 循环查询所有组织数据并同步到数据库
    private List<OrganizationItem> queryAllOrganizations(String accessToken) {
        List<OrganizationItem> allOrganizations = new ArrayList<>();
        int currentPage = DEFAULT_PAGE_NUM;

        // 先删除中间表数据
        deleteZJB();

        try {
            while (true) {
                // 构造分页参数
                String[] params = {
                        "pageSize=" + DEFAULT_PAGE_SIZE,
                        "pageNum=" + currentPage
                };

                // 调用单页查询接口
                mainDataLogger.info("正在查询组织数据（第{}页）", currentPage);
                String responseJson = sendHttpsGetWithOAuth(organizationApiBaseUrl, accessToken, params);
                OrganizationResponse orgResponse = gson.fromJson(responseJson, OrganizationResponse.class);

                // 校验响应
                if (orgResponse == null || !orgResponse.isSuccess() || orgResponse.getData() == null) {
                    String errMsg = String.format("第%d页组织查询失败，错误码：%s，错误信息：%s",
                            currentPage,
                            (orgResponse != null ? orgResponse.getCode() : "未知"),
                            (orgResponse != null ? orgResponse.getErrMsg() : "未知"));
                    mainDataLogger.error(errMsg);
                    throw new RuntimeException(errMsg);
                }

                OrganizationData orgData = orgResponse.getData();
                mainDataLogger.info("第{}页查询完成，当前页数据量：{}，总页数：{}",
                        currentPage,
                        (orgData.getPageData() != null ? orgData.getPageData().length : 0),
                        orgData.getTotalPage());

                // 收集当前页数据并同步到数据库
                if (orgData.getPageData() != null && orgData.getPageData().length > 0) {
                    allOrganizations.addAll(Arrays.asList(orgData.getPageData()));

                    // 同步当前页数据到数据库
                    for (OrganizationItem item : orgData.getPageData()) {
                        syncOrganizationToDb(item);
                    }
                }

                // 终止条件：当前页 >= 总页数
                if (currentPage >= orgData.getTotalPage()) {
                    mainDataLogger.info("所有组织数据查询完成！");
                    break;
                }

                // 准备查询下一页
                currentPage++;
            }
        } catch (Exception e) {
            mainDataLogger.error("组织分页循环查询异常", e);
            throw new RuntimeException("组织查询失败：" + e.getMessage());
        }

        return allOrganizations;
    }

    // 将单个组织数据同步到数据库
    private void syncOrganizationToDb(OrganizationItem item) {
        try {
            Number id = item.getId();
            String orgCode = item.getOrgCode();
            String orgName = item.getOrgName();
            String orgSn = item.getOrgSn();
            String orgType = item.getOrgType();
            String province = item.getProvince();
            String city = item.getCity();
            String county = item.getCounty();
            Number domainId = item.getDomainId();
            Number stat = item.getStat();
            Number sort = item.getSort();
            String allSort = item.getAllSort();
            String service = item.getService();
            Number forbidBindUser = item.getForbidBindUser();

            boolean success = batchInsertDepartments(id, orgCode, orgName, orgSn, orgType,
                    province, city, county, domainId, stat, sort, allSort, service, forbidBindUser);

            if (!success) {
                mainDataLogger.error("组织数据插入失败，组织id为:{}", item.getId());
            } else {
                mainDataLogger.info("组织数据插入成功，组织id为:{}", item.getId());
            }
        } catch (Exception e) {
            mainDataLogger.error("组织数据同步到数据库异常，组织id为:" + item.getId(), e);
        }
    }

    // 插入部门数据到数据库
    private boolean batchInsertDepartments(Number id, String orgCode, String orgName, String orgSn,
                                           String orgType, String province, String city, String county,
                                           Number domainId, Number stat, Number sort, String allSort,
                                           String service, Number forbidBindUser) {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
        dataSource.setUrl(dbUrl);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        // 插入中间表（参数化查询防止SQL注入）
        String sql = "INSERT INTO MJXTJK_ZZ_ZJB (ID, ORGCODE, ORGNAME, ORGSN, ORGTYPE, PROVINCE, CITY, COUNTY, " +
                "DOMAINID, STAT, SORT, ALLSORT, SERVICE, FORBIDBINDUSER, FORBIDBINDSERVICE, CREATE_TIME, UPDATE_TIME) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, SYSDATE, SYSDATE)";

        // 查询主表是否已存在该记录
        String checkSql = "select count(1) from MJXTJK_ZZ where id = ?";

        // 插入主表（参数化查询）
        String mainTableSql = "INSERT INTO MJXTJK_ZZ (ID, ORGCODE, ORGNAME, ORGSN, ORGTYPE, PROVINCE, CITY, COUNTY, " +
                "DOMAINID, STAT, SORT, ALLSORT, SERVICE, FORBIDBINDUSER, FORBIDBINDSERVICE, CREATE_TIME, UPDATE_TIME) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, SYSDATE, SYSDATE)";

        try {
            // 插入中间表
            int rowsAffected = jdbcTemplate.update(sql,
                    id, orgCode, orgName, orgSn, orgType, province, city, county,
                    domainId, stat, sort, allSort, service, forbidBindUser);

            // 检查主表是否存在该记录
            Integer count = jdbcTemplate.queryForObject(checkSql, new Object[]{id}, Integer.class);

            // 如果不存在则插入主表
            if (count != null && count == 0) {
                jdbcTemplate.update(mainTableSql,
                        id, orgCode, orgName, orgSn, orgType, province, city, county,
                        domainId, stat, sort, allSort, service, forbidBindUser);
            }

            return rowsAffected > 0;
        } catch (Exception e) {
            mainDataLogger.error("插入数据失败：" + e.getMessage(), e);
            return false;
        }
    }

    // 删除中间表数据
    private boolean deleteZJB() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
        dataSource.setUrl(dbUrl);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        String sql = "DELETE FROM MJXTJK_ZZ_ZJB";
        mainDataLogger.info("执行中间表删除语句: {}", sql);

        try {
            int rowsAffected = jdbcTemplate.update(sql);
            mainDataLogger.info("中间表删除完成，共删除 {} 条记录", rowsAffected);
            return rowsAffected >= 0;
        } catch (Exception e) {
            mainDataLogger.error("删除中间表数据失败：" + e.getMessage(), e);
            return false;
        }
    }

    // 工具方法：从公钥接口响应中提取公钥
    private String extractPublicKey(String jsonResponse) {
        try {
            ApiResponse response = gson.fromJson(jsonResponse, ApiResponse.class);
            if (response != null && response.isSuccess() && response.getData() != null) {
                String publicKey = response.getData().getPublicKey();
                mainDataLogger.info("提取到公钥：{}", publicKey);
                return publicKey;
            } else {
                mainDataLogger.error("提取公钥失败，响应：{}", jsonResponse);
                return null;
            }
        } catch (Exception e) {
            mainDataLogger.error("公钥解析异常", e);
            return null;
        }
    }

    // 工具方法：RSA公钥加密
    private String encrypt(String password, String publicKey) throws Exception {
        byte[] decodedPublicKey = java.util.Base64.getDecoder().decode(publicKey);
        RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(decodedPublicKey));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);

        byte[] inputBytes = password.getBytes(StandardCharsets.UTF_8);
        int inputLength = inputBytes.length;
        int MAX_ENCRYPT_BLOCK = 117;
        int offSet = 0;
        byte[] resultBytes = new byte[0];
        byte[] cache;

        while (inputLength - offSet > 0) {
            if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(inputBytes, offSet, MAX_ENCRYPT_BLOCK);
                offSet += MAX_ENCRYPT_BLOCK;
            } else {
                cache = cipher.doFinal(inputBytes, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
            System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
        }
        return java.util.Base64.getEncoder().encodeToString(resultBytes);
    }

    // 工具方法：关闭流和连接资源
    private void closeResources(BufferedReader reader, InputStream inputStream, HttpsURLConnection connection) {
        try {
            if (reader != null) reader.close();
            if (inputStream != null) inputStream.close();
            if (connection != null) connection.disconnect();
        } catch (IOException e) {
            mainDataLogger.error("资源关闭异常", e);
        }
    }

    // 内部类：用于接收API请求中的认证信息
    public static class AuthInfo {
        private String username;
        private String password;

        // Getters and Setters
        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }

    // 内部静态类：Token请求实体类
    private static class TokenRequest {
        private final String grant_type;
        private final String username;
        private final String password;
        private final String client_id;
        private final String client_secret;
        private final String public_key;

        public TokenRequest(String username, String encryptedPassword, String publicKey) {
            this.grant_type = fixedGrantType;  // 现在可以正常访问静态字段
            this.username = username;
            this.password = encryptedPassword;
            this.client_id = fixedClientId;    // 现在可以正常访问静态字段
            this.client_secret = fixedClientSecret;  // 现在可以正常访问静态字段
            this.public_key = publicKey;
        }

        // Gson序列化Getter
        public String getGrant_type() { return grant_type; }
        public String getUsername() { return username; }
        public String getPassword() { return password; }
        public String getClient_id() { return client_id; }
        public String getClient_secret() { return client_secret; }
        public String getPublic_key() { return public_key; }
    }

    // 内部静态类：Token响应实体类
    private static class TokenResponse {
        private boolean success;
        private TokenData data;
        private String code;
        private String errMsg;

        public boolean isSuccess() { return success; }
        public TokenData getData() { return data; }
        public String getCode() { return code; }
        public String getErrMsg() { return errMsg; }
    }

    // 内部静态类：Token响应数据体
    private static class TokenData {
        private String access_token;
        private String refresh_token;
        private long expires_in;
        private String token_type;

        public String getAccess_token() { return access_token; }
        public String getRefresh_token() { return refresh_token; }
        public long getExpires_in() { return expires_in; }
        public String getToken_type() { return token_type; }
    }

    // 内部静态类：组织分页查询响应实体类
    private static class OrganizationResponse {
        private boolean success;
        private OrganizationData data;
        private String code;
        private String errMsg;

        public boolean isSuccess() { return success; }
        public OrganizationData getData() { return data; }
        public String getCode() { return code; }
        public String getErrMsg() { return errMsg; }
    }

    // 内部静态类：组织分页查询数据体
    private static class OrganizationData {
        private OrganizationItem[] pageData;
        private int currentPage;
        private int totalPage;
        private int pageSize;
        private int totalRows;

        public OrganizationItem[] getPageData() { return pageData; }
        public int getCurrentPage() { return currentPage; }
        public int getTotalPage() { return totalPage; }
        public int getPageSize() { return pageSize; }
        public int getTotalRows() { return totalRows; }
    }

    // 内部静态类：组织信息实体类
    private static class OrganizationItem {
        private String service;
        private int id;
        private String orgCode;
        private String orgName;
        private String orgSn;
        private String orgType;
        private String province;
        private String city;
        private String county;
        private int domainId;
        private int stat;
        private int sort;
        private String allSort;
        private int forbidBindUser;
        private String forbidBindService;

        // Getter方法
        public String getService() { return service; }
        public int getId() { return id; }
        public String getOrgCode() { return orgCode; }
        public String getOrgName() { return orgName; }
        public String getOrgSn() { return orgSn; }
        public String getOrgType() { return orgType; }
        public String getProvince() { return province; }
        public String getCity() { return city; }
        public String getCounty() { return county; }
        public int getDomainId() { return domainId; }
        public int getStat() { return stat; }
        public int getSort() { return sort; }
        public String getAllSort() { return allSort; }
        public int getForbidBindUser() { return forbidBindUser; }
        public String getForbidBindService() { return forbidBindService; }
    }

    // 内部静态类：公钥接口响应实体类
    private static class ApiResponse {
        private boolean success;
        private Data data;
        private String code;
        private String errMsg;

        public boolean isSuccess() { return success; }
        public Data getData() { return data; }
        public String getCode() { return code; }
        public String getErrMsg() { return errMsg; }
    }

    private static class Data {
        private String publicKey;
        public String getPublicKey() { return publicKey; }
    }
}
